'use strict' // 启用严格模式，避免意外的全局变量等语法问题
// 引入 Node.js 的 path 模块，用于处理文件路径
const path = require('path')

// 封装路径解析函数：将相对路径转换为绝对路径（基于当前文件目录）
function resolve(dir) {
  // __dirname 是当前文件所在目录的绝对路径
  return path.join(__dirname, dir)
}

// 引入 compression-webpack-plugin 插件，用于构建时生成 Gzip 压缩文件
const CompressionPlugin = require('compression-webpack-plugin')

// 网页标题：优先从环境变量 VUE_APP_TITLE 获取，默认值为“若依管理系统”
const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题

// 后端接口基础地址：开发环境下前端请求会代理到这个地址（默认 http://localhost:8080，对应若依 Java 后端）
const baseUrl = 'http://localhost:8080' // 后端接口

// 前端开发服务器端口：优先从环境变量获取，默认 80
const port = process.env.port || process.env.npm_config_port || 80 // 端口

// vue.config.js 配置说明
//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
// 这里只列一部分，具体配置参考文档
module.exports = {
  // 部署生产环境和开发环境下的URL。
  // 默认情况下，Vue CLI 会假设你的应用是被部署在一个域名的根路径上
  // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上，你就需要用这个选项指定这个子路径。例如，如果你的应用被部署在 https://www.ruoyi.vip/admin/，则设置 baseUrl 为 /admin/。

  //publicPath：项目部署的基础路径（影响静态资源加载路径）。
  // 生产环境（production）：部署在域名根路径（如 https://xxx.com/）。
  // 开发环境（development）：本地开发路径（默认 /）。
  publicPath: process.env.NODE_ENV === "production" ? "/" : "/",

  // 在npm run build 或 yarn build 时 ，生成文件的目录名称（要和baseUrl的生产环境路径一致）（默认dist）
  //outputDir：执行 npm run build 时，打包生成的文件存放目录（默认 dist），需与生产环境的 publicPath 匹配。
  outputDir: 'dist',

  // 用于放置生成的静态资源 (js、css、img、fonts) 的；（项目打包之后，静态资源会放在这个文件夹下）
  //assetsDir：打包后静态资源（js、css、图片等）的存放子目录（最终路径为 dist/static）。
  assetsDir: 'static',

  // 如果你不需要生产环境的 source map，可以将其设置为 false 以加速生产环境构建。
  //productionSourceMap：生产环境是否生成 SourceMap（用于调试的映射文件）。设置为 false 可减小打包体积，加速生产环境构建。
  productionSourceMap: false,

  //transpileDependencies：指定需要通过 Babel 转译的依赖（默认只转译项目源码，第三方依赖不转译）。这里对 quill（富文本编辑器）进行转译，避免浏览器兼容问题。
  transpileDependencies: ['quill'],

  // webpack-dev-server 相关配置
  //核心作用：开发时前端请求（如 /dev-api/login）会被代理到后端接口（http://localhost:8080/login），解决浏览器跨域限制。
  devServer: {
    // 允许外部访问（如同一局域网内其他设备通过 IP 访问）
    host: '0.0.0.0',
    // 开发服务器端口（默认 80）
    port: port,
    //启动开发服务器后自动打开浏览器
    open: true,

    // 跨域代理配置（解决开发环境跨域问题）
    proxy: {
      // detail: https://cli.vuejs.org/config/#devserver-proxy

      // 第一组代理：匹配环境变量 VUE_APP_BASE_API 对应的路径（如 /dev-api）
      [process.env.VUE_APP_BASE_API]: {

        // 代理目标地址（后端接口地址 http://localhost:8080）
        target: baseUrl,
        // 开启跨域（修改请求头中的 Host 为目标地址）
        changeOrigin: true,

        // 路径重写：去掉请求路径中的 VUE_APP_BASE_API 前缀
        pathRewrite: {
          ['^' + process.env.VUE_APP_BASE_API]: ''
        }
      },

      // 第二组代理：匹配 swagger 接口文档路径（/v3/api-docs/xxx）
      // springdoc proxy
      '^/v3/api-docs/(.*)': {

        // 代理到后端，用于前端访问后端的 Swagger 文档
        target: baseUrl,
        changeOrigin: true
      }
    },

    // 关闭主机检查（避免本地开发时因主机名不匹配导致的访问限制）
    disableHostCheck: true
  },

  //自定义 CSS 预处理器（Sass）的编译选项，outputStyle: "expanded" 使编译后的 CSS 保持换行和缩进，便于开发调试。
  css: {
    loaderOptions: {
      sass: {
        // 配置 Sass 编译风格为展开式（非压缩）
        sassOptions: { outputStyle: "expanded" }
      }
    }
  },

  //用于直接修改 Webpack 配置，或添加插件。
  configureWebpack: {
    // 配置 Webpack 打包的名称（影响 HTML 中注入的资源名称）
    name: name,
    resolve: {
      alias: {
        // 配置路径别名：@ 指向 src 目录（如 @/views 等价于 src/views）
        '@': resolve('src')
      }
    },
    plugins: [
      // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件
      // 配置 Gzip 压缩插件（生产环境打包时生成 .gz 压缩文件）
      new CompressionPlugin({
        // 不缓存已压缩的文件
        cache: false,                                  // 不启用文件缓存

        // 匹配需要压缩的文件格式
        test: /\.(js|css|html|jpe?g|png|gif|svg)?$/i,  // 压缩文件格式

        // 压缩后的文件名（在原文件名后加 .gz）
        filename: '[path][base].gz[query]',            // 压缩后的文件名

        // 使用 gzip 算法压缩
        algorithm: 'gzip',                             // 使用gzip压缩

        // 只有压缩率（压缩后/压缩前）小于 0.8 的文件才会被保留
        minRatio: 0.8,                                 // 压缩比例，小于 80% 的文件不会被压缩

        // 压缩后不删除原文件（避免某些服务器不支持 gzip 时无法访问）
        deleteOriginalAssets: false                    // 压缩后删除原文件
      })
    ],
  },

  //通过链式调用的方式更精细地修改 Webpack 配置（比 configureWebpack 更灵活）。
  chainWebpack(config) {

    // 删除 preload 和 prefetch 插件（这两个插件用于预加载资源，若依项目中禁用以减少不必要的请求）
    config.plugins.delete('preload') // TODO: need test
    config.plugins.delete('prefetch') // TODO: need test

    // set svg-sprite-loader
    // 配置 SVG 处理规则：区分普通 SVG 和图标 SVG
    config.module
      // 普通 SVG 规则
      .rule('svg')
      // 排除图标目录（不使用默认 loader 处理）
      .exclude.add(resolve('src/assets/icons'))
      .end()
    config.module
      // 图标 SVG 规则
      .rule('icons')
      // 匹配图标目录下的 SVG
      .test(/\.svg$/)
      // 只处理图标目录
      .include.add(resolve('src/assets/icons'))
      .end()
      // 使用 svg-sprite-loader 加载（将 SVG 转为雪碧图）
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        // 定义图标 ID 格式（如 icon-user）
        symbolId: 'icon-[name]'
      })
      .end()

    // 生产环境优化配置（仅在非开发环境生效）
    config.when(process.env.NODE_ENV !== 'development', config => {
      // 配置 script-ext-html-webpack-plugin：将 runtime.js 内联到 HTML 中（减少请求次数）
          config
            .plugin('ScriptExtHtmlWebpackPlugin')
            // 在 html-webpack-plugin 之后执行
            .after('html')
            .use('script-ext-html-webpack-plugin', [{
            // `runtime` must same as runtimeChunk name. default is `runtime`
              // 匹配 runtime 开头的 JS 文件
              inline: /runtime\..*\.js$/
            }])
            .end()
          // 代码分割（SplitChunks）：将代码拆分为多个 chunk，优化缓存和加载速度
          config.optimization.splitChunks({
            // 对所有类型的 chunk（同步/异步）进行分割
            chunks: 'all',

            // 缓存组：按规则分组拆分
            cacheGroups: {
              // 第三方库（node_modules）
              libs: {
                name: 'chunk-libs',
                test: /[\\/]node_modules[\\/]/,
                // 优先级（数值越大越先匹配）
                priority: 10,
                // 只拆分初始加载的第三方库
                chunks: 'initial' // only package third parties that are initially dependent
              },

              // 单独拆分 element-ui（避免和其他库混在一起，优化缓存）
              elementUI: {
                name: 'chunk-elementUI', // split elementUI into a single package
                test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm

                // 优先级高于 libs，确保 element-ui 单独拆分
                priority: 20 // the weight needs to be larger than libs and app or it will be packaged into libs or app
              },

              // 公共组件（项目内复用的组件）
              commons: {
                name: 'chunk-commons',

                // 匹配 src/components 目录
                test: resolve('src/components'), // can customize your rules

                // 被至少 3 个地方引用才会被拆分
                minChunks: 3, //  minimum common number
                priority: 5,

                // 复用已有的 chunk（避免重复打包）
                reuseExistingChunk: true
              }
            }
          })

          // 将 runtime 代码（Webpack 运行时的辅助代码）拆分为单独的 chunk
          config.optimization.runtimeChunk('single')
    })
  }
}
